home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / packet / p_aa4re / mbb35src / 8250svc.asm < prev    next >
Encoding:
Assembly Source File  |  1991-02-16  |  35.8 KB  |  758 lines

  1. ;==========================================================================;
  2. ; 8250 Services                                                            ;
  3. ;   This code also used by the QUADRAM QUADPORT board and the              ;
  4. ;   4 async port card without change.                                      ;
  5. ;                                                                          ;
  6. ;   Copyright 1983 by William E. Westfield.  All rights reserved.          ;
  7. ;   Copyright 1986, 1987, 1988, 1991 by H. Roy Engehausen.                 ;
  8. ;   All rights reserved.                                                   ;
  9. ;                                                                          ;
  10. ;   This software may be freely distributed and used, but it may not       ;
  11. ;   under any circumstances be sold by anyone other than the author.       ;
  12. ;   It may be distributed by a commercial company as long as it is         ;
  13. ;   for no cost.                                                           ;
  14. ;                                                                          ;
  15. ;==========================================================================;
  16.  
  17. ;--------------------------------------------------------------------------;
  18. ; Branch to the proper service routine                                     ;
  19. ;                                                                          ;
  20. ;       AH=0    INITIALIZE                                                 ;
  21. ;               DX is the port number. (0 = COM1, 1 = COM2)                ;
  22. ;               AL is set according to the following table.                ;
  23. ;                                                                          ;
  24. ;     High speed option is off                                             ;
  25. ;       MSB                                                     LSB        ;
  26. ;        7       6       5       4       3       2       1       0         ;
  27. ;        ----data-rate----       -Parity--    Stopbits   --Word length--   ;
  28. ;                                                                          ;
  29. ;        000 -   110             X0 - none      0 - 1    10 - 7 bits       ;
  30. ;        001 -   150             01 - odd       1 - 2    11 - 8 bits       ;
  31. ;        010 -   300             11 - even                                 ;
  32. ;        011 -   600                                                       ;
  33. ;        100 -  1200                                                       ;
  34. ;        101 -  2400                                                       ;
  35. ;        110 -  4800                                                       ;
  36. ;        111 -  9600                                                       ;
  37. ;                                                                          ;
  38. ;     High speed option is on                                              ;
  39. ;        000 -    9600           X0 - none      0 - 1    10 - 7 bits       ;
  40. ;        001 -   14400           01 - odd       1 - 2    11 - 8 bits       ;
  41. ;        010 -   19200           11 - even                                 ;
  42. ;        011 -   28800                                                     ;
  43. ;        100 -   38400                                                     ;
  44. ;        101 -   57600                                                     ;
  45. ;        110 -  115200                                                     ;
  46. ;        111 -  330400                                                     ;
  47. ;                                                                          ;
  48. ;               Returns:                                                   ;
  49. ;                       AX = status according to function 3.               ;
  50. ;                       DX = unchanged                                     ;
  51. ;                                                                          ;
  52. ;       AH=1    SEND                                                       ;
  53. ;               DX is the port number. (0 = COM1, 1 = COM2)                ;
  54. ;               AL is the character to be sent.                            ;
  55. ;               Returns:                                                   ;
  56. ;                       AH = status according to function 3.               ;
  57. ;                       AL = unchanged                                     ;
  58. ;                       DX = unchanged                                     ;
  59. ;                                                                          ;
  60. ;       AH=2    RECEIVE                                                    ;
  61. ;               DX is the port number. (0 = COM1, 1 = COM2)                ;
  62. ;                                                                          ;
  63. ;               Returns:                                                   ;
  64. ;                       AH = status according to function 3.               ;
  65. ;                       AL = character read from buffer.                   ;
  66. ;                       DX = unchanged                                     ;
  67. ;                                                                          ;
  68. ;       AH=3    STATUS                                                     ;
  69. ;               DX is the port number. (0 = COM1, 1 = COM2)                ;
  70. ;                                                                          ;
  71. ;               Returns:                                                   ;
  72. ;               AH = Line Status Register                                  ;
  73. ;               AL = Modem Status Register                                 ;
  74. ;               DX = Unchanged                                             ;
  75. ;                                                                          ;
  76. ; If the extended 8250 functions are available, they are described later   ;
  77. ;--------------------------------------------------------------------------;
  78.  
  79.         MOV     BL,AH
  80.  IF present_8250x
  81.         CMP     BL,12               ; Validate the function code
  82.  ELSE
  83.         CMP     BL,3                ; Validate the function code
  84.  ENDIF
  85.         JA      rsint_8250_exit     ; Not a valid code
  86.         SUB     BH,BH               ; Zero the high order byte
  87.         SHL     BL,1                ; * 2
  88.         JMP     rsint_8250_jmp[BX]  ; Go to it
  89.  
  90. rsint_8250_jmp LABEL WORD           ;
  91.         DW      OFFSET rsint_8250_init     ; 0 = Initialize
  92.         DW      OFFSET rsint_8250_send     ; 1 = Send a character
  93.         DW      OFFSET rsint_8250_recv     ; 2 = Receive character
  94.         DW      OFFSET rsint_8250_status   ; 3 = Status
  95.  
  96.  IF present_8250x
  97.  
  98.  ; Extended function codes
  99.  
  100.         DW      OFFSET rsint_8250_inquiry  ; 4 = return footprint
  101.         DW      OFFSET rsint_8250_droprts  ; 5 = signal NO RTS/DTR
  102.         DW      OFFSET rsint_8250_raiserts ; 6 = signal RTS/DTR
  103.         DW      OFFSET rsint_8250_sendbrk  ; 7 = send break
  104.         DW      OFFSET rsint_8250_ndr      ; 8 = non destructive read
  105.         DW      OFFSET rsint_8250_sopt     ; 9 = set options
  106.         DW      OFFSET rsint_8250_buffw    ; A = block write
  107.         DW      OFFSET rsint_8250_buffr    ; B = block read
  108.         DW      OFFSET rsint_8250_ded      ; C = DED mode send/receive
  109.  
  110.  ENDIF
  111.  
  112. rsint_8250_exit:
  113.         JMP     rsint_exit          ;
  114.  
  115. ;==========================================================================;
  116. ; 8250 Bios constants                                                      ;
  117. ;==========================================================================;
  118.  
  119. ;--------------------------------------------------------------------------;
  120. ; Divisors for the different data rates.  The offset into the table        ;
  121. ;is the one from the IBM BIOS initialization parameters                    ;
  122. ;--------------------------------------------------------------------------;
  123.  
  124. divisor_8250 LABEL WORD             ;
  125.         DW      1047                ; 0 =  110
  126.         DW      768                 ; 1 =  150
  127.         DW      384                 ; 2 =  300
  128.         DW      192                 ; 3 =  600
  129.         DW      96                  ; 4 = 1200
  130.         DW      48                  ; 5 = 2400
  131.         DW      24                  ; 6 = 4800
  132.         DW      12                  ; 7 = 9600
  133.  
  134. ; High speed options
  135.         DW      12                  ; 0 =   9600
  136.         DW      9                   ; 1 =  14400
  137.         DW      6                   ; 2 =  19200
  138.         DW      4                   ; 3 =  28800
  139.         DW      3                   ; 4 =  38400
  140.         DW      2                   ; 5 =  57600
  141.         DW      1                   ; 6 = 115200
  142.         DW      0                   ; 7 = 330400
  143.  
  144. ;==========================================================================;
  145. ; Initialization routine                                                   ;
  146. ;==========================================================================;
  147.  
  148. rsint_8250_init:
  149.  
  150. ;--------------------------------------------------------------------------;
  151. ; Mark block as open                                                       ;
  152. ;--------------------------------------------------------------------------;
  153.  
  154.         OR      flags[SI],flags_in_use  ; This block is open!
  155.  
  156. ;--------------------------------------------------------------------------;
  157. ; Set data rate                                                            ;
  158. ;--------------------------------------------------------------------------;
  159.  
  160.         MOV     AH,AL               ; Save the parms for later
  161.  
  162.         MOV     BL,AH               ; Look up the baud rate
  163.         MOV     CL,4                ; parameter
  164.         ROL     BL,CL               ;
  165.         AND     BX,00001110B        ;
  166.         TEST    options[SI],opt_high ; High speed option?
  167.         JZ      rsint_8250_init_nohs ;     Nope
  168.         ADD     BX,00010000B        ;      Yep.. Offset
  169. rsint_8250_init_nohs:               ;
  170.         MOV     BX,divisor_8250[BX] ;
  171.  
  172.         MOV     CX,baseaddr[SI]     ; Get base address for chip
  173.         MOV     DX,CX               ; Address of LCR
  174.         ADD     DX,lcr_8250         ;
  175.         MOV     AL,lcr_8250_dlab    ; Enable access to divisor
  176.         OUT     DX,AL               ;
  177.  
  178.         MOV     DX,CX               ; Address of lower divisior half
  179.         ADD     DX,dll_8250         ;
  180.         MOV     AL,BL               ; Put lower half
  181.         OUT     DX,AL               ;
  182.  
  183.         MOV     DX,CX               ; Address of upper divisior half
  184.         ADD     DX,dlm_8250         ;
  185.         MOV     AL,BH               ; Put upper half
  186.         OUT     DX,AL               ;
  187.  
  188. ;--------------------------------------------------------------------------;
  189. ; Set the data bits, stop bits, and parity                                 ;
  190. ;--------------------------------------------------------------------------;
  191.  
  192.         MOV     AL,AH               ; Get parms back
  193.         AND     AL,00011111B        ; Throw away baud rate leaving the rest
  194.         MOV     DX,CX               ; Address of LCR
  195.         ADD     DX,lcr_8250         ;
  196.         OUT     DX,AL               ; Output the parms
  197.  
  198. ;--------------------------------------------------------------------------;
  199. ; Set interrupt enable register                                            ;
  200. ;--------------------------------------------------------------------------;
  201.  
  202.         MOV     AL,ier_8250_rda     ; Enable data interrupt only
  203.  
  204.         TEST    options[SI],opt_trbuf ; Transmit buffering turned on?
  205.         JZ      rsint_8250_initnotr   ;           No - Just want only 1 interrupt
  206.         OR      AL,ier_8250_thre+ier_8250_ms ;  Yes - We need both modem status enable
  207.                                     ;                 and THRE interrupts too
  208. rsint_8250_initnotr:
  209.  
  210.         MOV     DX,CX               ; Compute port address for the IER
  211.         ADD     DX,ier_8250         ;
  212.         OUT     DX,AL               ; Set the IER
  213.  
  214. ;--------------------------------------------------------------------------;
  215. ; Done with initialization                                                 ;
  216. ;--------------------------------------------------------------------------;
  217.  
  218.         JMP     rsint_8250_status   ; Now just status please
  219.  
  220. ;==========================================================================;
  221. ; Send a character                                                         ;
  222. ;==========================================================================;
  223.  
  224. ;--------------------------------------------------------------------------;
  225. ; There are two places where the branch from the non-interrupt             ;
  226. ; driven code to the interrupt driven code is taken so be careful          ;
  227. ;--------------------------------------------------------------------------;
  228.  
  229. rsint_8250_send:
  230.  
  231.         MOV     AH,AL               ; Save the character to send
  232.         MOV     CX,baseaddr[SI]     ; Get base address for chip
  233.  
  234. ;--------------------------------------------------------------------------;
  235. ; Two separate routines, one for trasmit buffering and one if not!         ;
  236. ;--------------------------------------------------------------------------;
  237.  
  238.         TEST    options[SI],opt_trbuf ; Transmit buffering turned on?
  239.         JNZ     rsint_8250_send_bh  ;        Yes.. go there now!
  240.  
  241. ;--------------------------------------------------------------------------;
  242. ; Unbuffered send                                                          ;
  243. ;--------------------------------------------------------------------------;
  244.  
  245.         CALL    rsint_8250_send_unb ; Send unbuffered
  246.         JMP     rsint_8250_status   ; Go do a status
  247.  
  248. ;--------------------------------------------------------------------------;
  249. ; Buffered send starts here                                                ;
  250. ;--------------------------------------------------------------------------;
  251.  
  252. rsint_8250_send_bh:
  253.  
  254.         CLI                         ; Prevent status change
  255.  
  256.         TEST    options[SI],opt_hdwhs ; Hardware handshaking desired?
  257.         JZ      rsint_8250_sendb_ok ;      Nope
  258.  
  259. ;--------------------------------------------------------------------------;
  260. ; Buffered send -- hardware handshaking.  If the remote says no, go        ;
  261. ; immediately to buffered send                                             ;
  262. ;--------------------------------------------------------------------------;
  263.  
  264.         CALL    rsint_8250_msr      ; Get the MSR
  265.         AND     AL,msr_8250_cts     ; CTS on?
  266.         JZ      rsint_8250_sendb_fb ; Go to a spot where buffering is forced
  267.  
  268. ;--------------------------------------------------------------------------;
  269. ; This section is entered when its ok to send a character if the           ;
  270. ; buffer is empty.  Its either entered by the buffer handler above         ;
  271. ; when handshaking is enabled and the remote says go or from the           ;
  272. ; non-interrupt driven code if there is no handshaking                     ;
  273. ;--------------------------------------------------------------------------;
  274.  
  275. rsint_8250_sendb_ok:
  276.  
  277. ;--------------------------------------------------------------------------;
  278. ; Here we determine if the buffer is empty.  If it is, we can send         ;
  279. ; something right now.                                                     ;
  280. ;--------------------------------------------------------------------------;
  281.  
  282.         MOV     BX,buffer_t_in[SI]  ; Get buffer input pointer
  283.         CMP     BX,buffer_t_out[SI] ; See where the out pointer is
  284.         JNE     rsint_8250_sendb_fb2; If they are not equal then we have
  285.                                     ; data in the buffer
  286.  
  287.         MOV     DX,CX               ; Compute port address for the LSR
  288.         ADD     DX,lsr_8250         ;
  289.         IN      AL,DX               ; Get the LSR into AX
  290.         AND     AL,lsr_8250_thre    ; THR empty?
  291.         JZ      rsint_8250_sendb_fb2;      No.. Put character into the buffer
  292.  
  293.         STI                         ; AOK now
  294.  
  295. ; If we get here, the buffer is empty, the transmitter is ready, and
  296. ;      handshaking says it is ok to go!
  297.  
  298.         CALL    rsint_8250_send_subr ; Send the character
  299.  
  300.         JMP     SHORT rsint_8250_send_exit ; Now jump down to leave
  301.  
  302. ;--------------------------------------------------------------------------;
  303. ; This code puts the data into the buffer.                                 ;
  304. ;--------------------------------------------------------------------------;
  305.  
  306. rsint_8250_sendb_fb:                ; Use this entry point if hardware
  307.                                     ; handshake says distant end is not ready
  308.                                     ; We have to do some setup
  309.  
  310.         MOV     BX,buffer_t_in[SI]  ; Get buffer input pointer
  311.  
  312. rsint_8250_sendb_fb2:               ; Use this entry point if hardware
  313.                                     ; handshake was ok or not enabled.
  314.                                     ; All the setup is done when we get here
  315.  
  316.         MOV     ES,buffer_t_a[SI]   ; Get buffer segment
  317.         MOV     ES:[BX],AH          ; Get character into buffer..
  318.  
  319. ;--------------------------------------------------------------------------;
  320. ; Bump the input pointer and handle the special case of where we wrap      ;
  321. ; from one end of the buffer into the other                                ;
  322. ;--------------------------------------------------------------------------;
  323.  
  324.         INC     BX                  ; Bump pointer
  325.         CMP     BX,buffer_size      ; Have we wrapped the buffer?
  326.         JL      rsint_8250_sendb_bump ;    No.. All done
  327.         SUB     BX,BX               ;      Yes.. Reset pointer
  328. rsint_8250_sendb_bump:
  329.  
  330.         MOV     buffer_t_in[SI],BX  ; Save pointer
  331.  
  332.         STI                         ; OK for changes now...
  333.  
  334. ;--------------------------------------------------------------------------;
  335. ; If we have a destructive overlay possible then loop waiting for it to    ;
  336. ; clear.  Since the pointer in BX is to the location of the next character ;
  337. ; the we will overlap if it is the same as the pointer for the next        ;
  338. ; character to send.  The actual sending will be done by the interrupt     ;
  339. ; handler.  All we have to do is waint until the interrupt handler         ;
  340. ; has cleaned some characters out of the buffer                            ;
  341. ;--------------------------------------------------------------------------;
  342.  
  343. rsint_8250_sendb_bad:
  344.         CMP     BX,buffer_t_out[SI] ; See where the out pointer is
  345.  
  346.   IF present_dv                     ; Put in the desqview wait hook as needed
  347.  
  348.         JNE     rsint_8250_send_exit ; If they are not equal then we are ok
  349. dv_cnt = dv_cnt + 1
  350.         dv_hook %dv_cnt
  351.         CALL    desqview
  352.         JMP     SHORT rsint_8250_sendb_bad
  353.  
  354.   ELSE
  355.  
  356.         JE      rsint_8250_sendb_bad ; If they are not equal then we are ok
  357.  
  358.   ENDIF
  359.  
  360. ;--------------------------------------------------------------------------;
  361. ; We come here when we have sent the character immediately.                ;
  362. ;--------------------------------------------------------------------------;
  363.  
  364. rsint_8250_send_exit:
  365.  
  366. ;--------------------------------------------------------------------------;
  367. ; All done, do a status                                                    ;
  368. ;--------------------------------------------------------------------------;
  369.  
  370.         JMP     rsint_8250_status   ; Do a status
  371.  
  372. ;--------------------------------------------------------------------------;
  373. ;--------------------------------------------------------------------------;
  374. ; Subroutine to send unbuffered                                            ;
  375. ;--------------------------------------------------------------------------;
  376.  
  377. rsint_8250_send_unb:
  378.  
  379.         TEST    options[SI],opt_hdwhs ; Hardware handshaking desired?
  380.         JZ      rsint_8250_send_nbok ;     Nope
  381.  
  382.   IF present_dv                     ;
  383.         JMP     SHORT rsint_8250_send_nbl_dv ; First time jump over dv hook
  384.   ENDIF
  385.  
  386. ; Hardware handshake loop for unbuffered sending
  387.  
  388. rsint_8250_send_nbl:                ; Loop here until we can send
  389.  
  390.   IF present_dv                     ; Put in the desqview wait hook as needed
  391.  
  392. dv_cnt = dv_cnt + 1
  393.         dv_hook %dv_cnt
  394.         CALL    desqview
  395.  
  396. rsint_8250_send_nbl_dv:             ; Enter loop here when in desqview
  397.  
  398.   ENDIF
  399.  
  400.  
  401.         CALL    rsint_8250_msr      ; Get the MSR
  402.  
  403.         AND     AL,msr_8250_cts     ; CTS on?
  404.         JZ      rsint_8250_send_nbl ;      No.. Loop back
  405.  
  406. rsint_8250_send_nbok:               ;
  407.  
  408. ; Unbuffered sending.. Now ready to transmit
  409. ; ***** FALL THRU
  410.  
  411. ;--------------------------------------------------------------------------;
  412. ;--------------------------------------------------------------------------;
  413. ; Subroutine to send the character in AH                                   ;
  414. ;      *** WARNING *** also entered by fall thru from above                ;
  415. ;--------------------------------------------------------------------------;
  416.  
  417. rsint_8250_send_subr:
  418.  
  419. ;--------------------------------------------------------------------------;
  420. ; Loop waiting for TBE                                                     ;
  421. ;--------------------------------------------------------------------------;
  422.  
  423.         MOV     DX,CX               ; Compute port address for the LSR
  424.         ADD     DX,lsr_8250         ;
  425.  
  426.   IF present_dv                     ; Put in the desqview wait hook as needed
  427.         JMP     SHORT rsint_8250_send_sublp_dv ; First time jump over dv hook
  428.   ENDIF
  429.  
  430. rsint_8250_send_sublp:              ; Loop here until we can send
  431.  
  432.   IF present_dv                     ; Put in the desqview wait hook as needed
  433.  
  434. dv_cnt = dv_cnt + 1
  435.         dv_hook %dv_cnt
  436.         CALL    desqview
  437.  
  438. rsint_8250_send_sublp_dv:           ; First time we jump here in desqview mode
  439.  
  440.   ENDIF
  441.  
  442.         IN      AL,DX               ; Get the LSR into AX
  443.         AND     AL,lsr_8250_thre    ; THR empty?
  444.         JZ      rsint_8250_send_sublp  ;   No.. Loop back
  445.  
  446. ;--------------------------------------------------------------------------;
  447. ; Out the character                                                        ;
  448. ;--------------------------------------------------------------------------;
  449.  
  450.         MOV     AL,AH               ; Get ready to out character
  451.  
  452.         MOV     DX,CX               ; Compute port address for the THR
  453. ;       ADD     DX,thr_8250         ;      and then
  454.         OUT     DX,AL               ;      out the character
  455. ; The add of THR is commented out since the THR is at zero from
  456. ; the base.  This just documents the fact we are going for the THR
  457.  
  458. ;--------------------------------------------------------------------------;
  459. ; Turn on the character sent flag                                          ;
  460. ;--------------------------------------------------------------------------;
  461.  
  462.         OR      flags[SI],flags_xmt_on ; Turn on transmitter flag
  463.  
  464.         RET                         ; Return to sender
  465.  
  466. ;==========================================================================;
  467. ; Receive a character                                                      ;
  468. ;==========================================================================;
  469.  
  470. rsint_8250_recv:
  471.  
  472.         MOV     CX,baseaddr[SI]     ; Get base address for chip
  473.  
  474. ;--------------------------------------------------------------------------;
  475. ; Loop waiting for something to appear in the buffer.  We do this          ;
  476. ; by comparing the input and output pointers.  If they are the same        ;
  477. ; same then there is nothing in the buffer                                 ;
  478. ;--------------------------------------------------------------------------;
  479.  
  480.         MOV     BX,buffer_r_out[SI] ; Get buffer output pointer
  481.  
  482.   IF present_dv                     ; If desqview presentthen skip the hook
  483.         JMP     SHORT rsint_8250_recv_rdy
  484.   ENDIF
  485.  
  486. rsint_8250_recv_loop:
  487.  
  488.   IF present_dv                     ; Put in the desqview wait hook as needed
  489.  
  490. dv_cnt = dv_cnt + 1
  491.         dv_hook %dv_cnt
  492.         CALL    desqview
  493.  
  494. rsint_8250_recv_rdy:                ; Come here to start when in desqview mode
  495.  
  496.   ENDIF
  497.  
  498.  
  499.         CMP     BX,buffer_r_in[SI]  ; See in anything in buffer
  500.         JE      rsint_8250_recv_loop ;     Nope.. Keep looping
  501.  
  502. ;--------------------------------------------------------------------------;
  503. ; Something is here..  Remove the character from the buffer                ;
  504. ;--------------------------------------------------------------------------;
  505.  
  506.         MOV     ES,buffer_r_a[SI]   ; Get buffer segment
  507.         MOV     AH,ES:[BX]          ; Get character from buffer.. Hide it in AH
  508.  
  509. ;--------------------------------------------------------------------------;
  510. ; Bump the output pointer and handle the special case of where we wrap     ;
  511. ; from one end of the buffer into the other                                ;
  512. ;--------------------------------------------------------------------------;
  513.  
  514.         INC     BX                  ; Bump pointer
  515.         CMP     BX,buffer_size      ; Have we wrapped the buffer?
  516.         JL      rsint_8250_recv_exit ;     No.. All done
  517.         SUB     BX,BX               ;      Yes.. Reset pointer
  518. rsint_8250_recv_exit:
  519.  
  520.         MOV     buffer_r_out[SI],BX ; Save pointer
  521.  
  522. ;--------------------------------------------------------------------------;
  523. ; If we have hardware handshaking enabled, then see if we need to          ;
  524. ; signal start.  1/16 is the limit we are using                            ;
  525. ;--------------------------------------------------------------------------;
  526.  
  527.         TEST    options[SI],opt_hdwhs ; Hardware handshaking desired?
  528.         JZ      rsint_8250_r_nohshak  ;      Nope
  529.         TEST    flags[SI],flags_useoff ; Does user wants handshake off?
  530.         JNZ     rsint_8250_r_nohshak  ;      Yep...  We dont touch it here
  531.  
  532.         MOV     DX,BX               ; Put pointer in work reg
  533.         SUB     DX,buffer_r_in[SI]  ; Compute the delta
  534.         JG      rsint_8250_rpos     ;        Jump over if positive result
  535.         ADD     DX,buffer_size      ; This will convert it back to positive
  536. rsint_8250_rpos:                    ; DX now is equal to bytes free!
  537.  
  538.         CMP     DX,(buffer_size / 8) ; See if at least 1/8 is left
  539.         JL      rsint_8250_r_stop   ;         No... Leave stop on
  540.  
  541.         MOV     DX,CX               ; Get base address for chip
  542.         ADD     DX,mcr_8250         ;
  543.         MOV     AL,hon_8250         ; Raise DTR, RTS, and OUT2.  OUT2 turns
  544.         OUT     DX,AL               ; on interrupts.
  545.  
  546. rsint_8250_r_stop:                  ;
  547.  
  548. rsint_8250_r_nohshak:               ;
  549.  
  550. ;--------------------------------------------------------------------------;
  551. ; Remember we hid the receive character in AH... Put it where it belongs   ;
  552. ; now                                                                      ;
  553. ;--------------------------------------------------------------------------;
  554.  
  555.         MOV     AL,AH               ;
  556.  
  557. ;--------------------------------------------------------------------------;
  558. ; Put out the last LSR we received with the exception of RDA.  If we have  ;
  559. ; no pending LSR, go get one                                               ;
  560. ;--------------------------------------------------------------------------;
  561.  
  562.         SUB     AH,AH               ; Get the last LSR and
  563.         XCHG    AH,last_rs[SI]      ;  clear it too!
  564.  
  565.         OR      AH,AH               ; Is it non-existant?
  566.         JNZ     rsint_8250_rcv_nolsr;      Nope
  567.  
  568.         MOV     AH,AL               ; Save the received character
  569.  
  570.         MOV     DX,CX               ; Get base address for chip
  571.         ADD     DX,lsr_8250         ; Now get a real LSR
  572.         IN      AL,DX               ;
  573.  
  574.         XCHG    AH,AL               ; Put things back together
  575.  
  576. rsint_8250_rcv_nolsr:
  577.  
  578. ;--------------------------------------------------------------------------;
  579. ; Set the RDA bit based on buffer status                                   ;
  580. ;--------------------------------------------------------------------------;
  581.  
  582.         AND     AH,0FFH-lsr_8250_dr ; Remove data ready bit
  583.  
  584.         CMP     BX,buffer_r_in[SI]  ; Anything left in buffer?
  585.         JE      rsint_8250_rcv_go   ;      Nope so leave
  586.         OR      AH,lsr_8250_dr      ; Turn on data ready
  587. rsint_8250_rcv_go:                  ;
  588.  
  589. ;--------------------------------------------------------------------------;
  590. ; Done                                                                     ;
  591. ;--------------------------------------------------------------------------;
  592.  
  593.         JMP     rsint_exit          ;      and go leave
  594.  
  595. ;==========================================================================;
  596. ; Status..   Return the MSR and the LSR                                    ;
  597. ;==========================================================================;
  598.  
  599. rsint_8250_status:
  600.  
  601.         MOV     CX,baseaddr[SI]     ; Get base address for chip
  602.  
  603. ;--------------------------------------------------------------------------;
  604. ; Put out the current LSR plus the current Receive Data Available          ;
  605. ; setting based on the buffer contents plus last_lsr                       ;
  606. ;--------------------------------------------------------------------------;
  607.  
  608.         MOV     DX,CX               ; Compute port address for the LSR
  609.         ADD     DX,lsr_8250         ;      and then
  610.         JMP     $+2                 ;
  611.         IN      AL,DX               ;      get it
  612.  
  613.         SUB     AH,AH               ; Get the last LSR and clear it too.
  614.         XCHG    AH,last_rs[SI]      ;
  615.         OR      AL,AH               ; OR it in
  616.  
  617.         AND     AL,0FFH-lsr_8250_dr ; Remove data ready bit
  618.  
  619.         MOV     BX,buffer_r_out[SI] ; Get buffer output pointer
  620.         CMP     BX,buffer_r_in[SI]  ; Anything left in buffer?
  621.         JE      rsint_8250_status_nodr ;   Nope so leave
  622.         OR      AL,lsr_8250_dr      ; Turn on data ready
  623. rsint_8250_status_nodr:
  624.  
  625.         MOV     AH,AL               ; Save LSR
  626.  
  627. ;--------------------------------------------------------------------------;
  628. ; Now lets get the MSR                                                     ;
  629. ;--------------------------------------------------------------------------;
  630.  
  631.         CALL    rsint_8250_msr      ; Get the MSR
  632.  
  633. ;--------------------------------------------------------------------------;
  634. ; Save both the real LSR and the real MSR for later                        ;
  635. ;--------------------------------------------------------------------------;
  636.  
  637.         MOV     DX,AX               ;
  638.  
  639. ;--------------------------------------------------------------------------;
  640. ; If we have transmit buffering active then we adjust the TBE and CTS      ;
  641. ; bits based on current state of transmit buffers etc...                   ;
  642. ;--------------------------------------------------------------------------;
  643.  
  644.         TEST    options[SI],opt_trbuf ; Transmit buffering turned on?
  645.         JZ      rsint_8250_status_notb;      Nope... Skip this
  646.  
  647. ;--------------------------------------------------------------------------;
  648. ; If the buffer is empty, use the TBE as set by the chip.  In all          ;
  649. ; other cases, TBE should be off since there is data in the buffer         ;
  650. ;--------------------------------------------------------------------------;
  651.  
  652.         MOV     BX,buffer_t_out[SI] ; Get buffer output pointer
  653.         SUB     BX,buffer_t_in[SI]  ; Get buffer input pointer
  654.         JG      rsint_8250_status_tpos ;  Jump over if positive result
  655.         ADD     BX,buffer_size      ; This will convert it back to positive
  656. rsint_8250_status_tpos:             ; BX now is equal to bytes left!
  657.  
  658.         CMP     BX,buffer_size      ; Max amount left in buffer?
  659.         JE      rsint_8250_status_empty;   Yes.. Use the chip's THRE
  660.  
  661.         AND     AH,0FFH-lsr_8250_thre ; Remove transmit holding register empty
  662. rsint_8250_status_empty:
  663.  
  664. ;--------------------------------------------------------------------------;
  665. ; Hardware handshaking?  If not, we can go                                 ;
  666. ;--------------------------------------------------------------------------;
  667.  
  668.         TEST    options[SI],opt_hdwhs ; Hardware handshaking desired?
  669.         JZ      rsint_8250_t_nostop  ;      Nope... we are done
  670.  
  671. ;--------------------------------------------------------------------------;
  672. ; If the remote signals stop, so will we...                                ;
  673. ;--------------------------------------------------------------------------;
  674.  
  675.         TEST    DL,msr_8250_cts     ; See Clear to send (CTS) on from remote?
  676.         JZ      rsint_8250_status_tstop ;     Nope..... Stop sending!
  677.  
  678. ;--------------------------------------------------------------------------;
  679. ; Now we assume that we have a CTS on!   ..                                ;
  680. ;--------------------------------------------------------------------------;
  681.  
  682.         OR      AL,msr_8250_cts     ; Set Clear to send (CTS)
  683.  
  684.                                     ; CTS is already on...
  685.                                     ; becuz there is data in the buffer
  686.  
  687. ;--------------------------------------------------------------------------;
  688. ; See if any room left in buffer.  If so, we can go                        ;
  689. ;--------------------------------------------------------------------------;
  690.  
  691.         CMP     BX,(buffer_size / 4) ; See if at least 1/4 is left
  692.         JGE     rsint_8250_t_nostop  ;      Yes.. No stop needed
  693.  
  694. ;--------------------------------------------------------------------------;
  695. ; Signal to stop sending!                                                  ;
  696. ;--------------------------------------------------------------------------;
  697.  
  698. rsint_8250_status_tstop:
  699.  
  700.         AND     AH,0FFH-lsr_8250_thre ; Remove transmit holding register empty
  701.         AND     AL,0FFH-msr_8250_cts  ; Remove Clear to send (CTS)
  702.  
  703. rsint_8250_t_nostop:
  704.  
  705. rsint_8250_status_notb:
  706.  
  707. ;--------------------------------------------------------------------------;
  708. ; All done                                                                 ;
  709. ;--------------------------------------------------------------------------;
  710.  
  711.         JMP     rsint_exit          ; All done
  712.  
  713. ;==========================================================================;
  714. ; Subroutine to get the MSR...  Why is special???  Because it could        ;
  715. ; accidentally wipe out the pending modem state change interrupt           ;
  716. ; Inputs  : CX = port base address                                         ;
  717. ; Outputs : AL = MSR                                                       ;
  718. ; Registers used: DX                                                       ;
  719. ;==========================================================================;
  720.  
  721. rsint_8250_msr:
  722.  
  723.         MOV     DX,CX               ; Compute port address for the MSR
  724.         ADD     DX,msr_8250         ;      and then
  725.         IN      AL,DX               ;      get it
  726.         TEST    AL,msr_8250_dcts    ; Delta CTS?
  727.         JZ      SHORT rsint_8250_msr_exit ; Nope..... leave...
  728.         TEST    AL,msr_8250_cts     ; CTS on?
  729.         JZ      SHORT rsint_8250_msr_exit ; Nope..... leave...
  730.  
  731. ; We have accidentally eaten an interrupt intended for the handler...
  732. ;      Now create a pseudo interrupt!
  733.  
  734.         MOV     DL,hiv[SI]          ; Get the hardware interrupt vector address
  735.         MOV     rsint_8250_msr_int,DL ; Put it where we need it
  736.  
  737.         JMP     $+2                 ; Clean out prefetch stack
  738.         INT     00H                 ; Interrupt!
  739.         ORG     $-1
  740. rsint_8250_msr_int DB  ?            ; Place to put interrupt number
  741.  
  742.                                     ; We are going to exit here with interrupt
  743.                                     ; masked since we will exit in a very very short
  744.                                     ; time
  745.  
  746. rsint_8250_msr_exit:
  747.         RET                         ; Return to caller
  748.  
  749. ;==========================================================================;
  750. ; Extended service routines are below (if any)                             ;
  751. ;==========================================================================;
  752.  
  753.  IF present_8250x
  754.  
  755.   INCLUDE 8250svcx.asm ;
  756.  
  757.  ENDIF
  758.